﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EventHandler.Libraries.Business.Security;
using System.Data;
using EventHandler.Libraries.Business.Database;

namespace EventHandler.Libraries.Business.Event
{
    public class EventItemHelper : IEventItemHelper
    {
        private readonly IDatabaseHelper _dbHelper;

        public EventItemHelper(IDatabaseHelper db)
        {
            _dbHelper = db;
        }

        public int CreateEvent(ICreateEventItem newEvent)
        {
            if (newEvent == null)
            {
                throw new ArgumentNullException("Event");
            }

            ValidateCreate(newEvent);

            int eventId = -1;

            using (var cn = _dbHelper.GetConnection())
            {
                cn.Open();

                var cmd = cn.CreateCommand();
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "Event.CreateNewEvent";

                var titleParameter = cmd.CreateParameter();
                titleParameter.ParameterName = "@EventTitle";
                titleParameter.DbType = DbType.String;
                titleParameter.Size = 255;
                titleParameter.Value = newEvent.Title;
                cmd.Parameters.Add(titleParameter);

                var ownerIdParameter = cmd.CreateParameter();
                ownerIdParameter.ParameterName = "@OwnerId";
                ownerIdParameter.DbType = DbType.Int32;
                ownerIdParameter.Value = newEvent.OwnerId;
                cmd.Parameters.Add(ownerIdParameter);

                var eventIdOutputParameter = cmd.CreateParameter();
                eventIdOutputParameter.ParameterName = "@EventId";
                eventIdOutputParameter.DbType = DbType.Int32;
                eventIdOutputParameter.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(eventIdOutputParameter);


                cmd.ExecuteNonQuery();

                eventId = (int)eventIdOutputParameter.Value;

                cn.Close();
            }
            return eventId;
        }

        private static void ValidateCreate(ICreateEventItem newEvent)
        {
            var errors = new StringBuilder();
            if (string.IsNullOrEmpty(newEvent.Title))
            {
                errors.Append("Title is required\n");
            }
            if (newEvent.OwnerId <= 0)
            {
                errors.Append("OwnerId is required\n");
            }
            if (errors.Length > 0)
            {
                throw new ArgumentException(errors.ToString());
            }
        }

        public void DeleteEvent(IDeleteEventItem deleteEvent)
        {
            if (deleteEvent == null)
            {
                throw new ArgumentNullException("Delete Event");
            }

            ValidateDelete(deleteEvent);

            using (var cn = _dbHelper.GetConnection())
            {
                cn.Open();

                var cmd = cn.CreateCommand();
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "Event.DeleteEvent";

                var eventParameter = cmd.CreateParameter();
                eventParameter.ParameterName = "@EventID";
                eventParameter.DbType = DbType.Int32;
                eventParameter.Value = deleteEvent.EventId;
                cmd.Parameters.Add(eventParameter);
                var ownerIdParameter = cmd.CreateParameter();
                ownerIdParameter.ParameterName = "@OwnerID";
                ownerIdParameter.DbType = DbType.Int32;
                ownerIdParameter.Value = deleteEvent.OwnerId;
                cmd.Parameters.Add(ownerIdParameter);

                cmd.ExecuteNonQuery();
                cn.Close();
            }
        }

        private static void ValidateDelete(IDeleteEventItem deleteEvent)
        {
            var errors = new StringBuilder();
            if (deleteEvent.EventId <= 0)
            {
                errors.Append("EventId is required\n");
            }
            if (deleteEvent.OwnerId <= 0)
            {
                errors.Append("OwnerId is required\n");
            }
            if (errors.Length > 0)
            {
                throw new ArgumentException(errors.ToString());
            }
        }

        public void RegisterForEvent(IRegisterEventItem registerEventItem)
        {
            if (registerEventItem == null)
            {
                throw new ArgumentNullException("Register For Event");
            }

            ValidateRegisterForEvent(registerEventItem);

            using (var cn = _dbHelper.GetConnection())
            {
                cn.Open();

                var cmd = cn.CreateCommand();
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "Auth.RegisterForEvent";

                var eventParameter = cmd.CreateParameter();
                eventParameter.ParameterName = "@EventID";
                eventParameter.DbType = DbType.Int32;
                eventParameter.Value = registerEventItem.EventId;
                cmd.Parameters.Add(eventParameter);
                var ownerIdParameter = cmd.CreateParameter();
                ownerIdParameter.ParameterName = "@OwnerID";
                ownerIdParameter.DbType = DbType.Int32;
                ownerIdParameter.Value = registerEventItem.OwnerId;
                cmd.Parameters.Add(ownerIdParameter);

                cmd.ExecuteNonQuery();
                cn.Close();
            }
        }

        private static void ValidateRegisterForEvent(IRegisterEventItem registerEventItem)
        {
            var errors = new StringBuilder();
            if (registerEventItem.EventId <= 0)
            {
                errors.Append("EventId is required\n");
            }
            if (registerEventItem.OwnerId <= 0)
            {
                errors.Append("OwnerId is required\n");
            }
            if (errors.Length > 0)
            {
                throw new ArgumentException(errors.ToString());
            }
        }

        public int UpdateEvent(IUpdateEventItem newEvent)
        {
            if (newEvent == null)
            {
                throw new ArgumentNullException("Event");
            }

            ValidateUpdate(newEvent);


            int eventId = -1;

            using (var cn = _dbHelper.GetConnection())
            {
                cn.Open();

                var cmd = cn.CreateCommand();
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "Event.UpdateEvent";

                var titleParameter = cmd.CreateParameter();
                titleParameter.ParameterName = "@EventTitle";
                titleParameter.DbType = DbType.String;
                titleParameter.Size = 255;
                titleParameter.Value = newEvent.Title;
                cmd.Parameters.Add(titleParameter);

                var eventIdOutputParameter = cmd.CreateParameter();
                eventIdOutputParameter.ParameterName = "@EventId";
                eventIdOutputParameter.DbType = DbType.Int32;
                eventIdOutputParameter.Direction = ParameterDirection.Output;
                cmd.Parameters.Add(eventIdOutputParameter);


                cmd.ExecuteNonQuery();

                eventId = (int)eventIdOutputParameter.Value;

                cn.Close();
            }
            return eventId;
        }

        private static void ValidateUpdate(IUpdateEventItem newEvent)
        {
            var errors = new StringBuilder();
            if (string.IsNullOrEmpty(newEvent.Title))
            {
                errors.Append("Title is required\n");
            }
            if (newEvent.EventId <= 0)
            {
                errors.Append("EventId is invalid\n");
            }   
            if (errors.Length > 0)
            {
                throw new ArgumentException(errors.ToString());
            }
        }
    }
}
